Skip to content

feat: v3 invoice api get review - #4573

Merged
tothandras merged 2 commits into
feat/v3-invoice-api-getfrom
feat/v3-invoice-api-get-review
Jun 25, 2026
Merged

feat: v3 invoice api get review#4573
tothandras merged 2 commits into
feat/v3-invoice-api-getfrom
feat/v3-invoice-api-get-review

Conversation

@tothandras

@tothandras tothandras commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features
    • Updated invoice/charge contracts with clearer Charge*/Invoice* naming plus lifecycle_controller.
    • Switched identifier modeling to external_references (including payment/invoicing context).
    • Added support for linking invoice lines to charges.
  • Bug Fixes
    • Billing party address snapshots now retain partially provided address details.
  • Breaking Changes
    • Major API/schema renames (e.g., external_idsexternal_references, managed_bylifecycle_controller, billingAddressaddress) and invoice model restructuring.
    • Credit-note invoice variants were removed/disabled.
  • Documentation
    • AIP-126 unknown enum member guidance is now a recommendation.

@tothandras
tothandras requested a review from a team as a code owner June 25, 2026 18:29
@tothandras tothandras added the release-note/feature Release note: Exciting New Features label Jun 25, 2026
@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Billing charge, customer, and invoice contracts are renamed across the API spec, generated client, Go handlers, and e2e coverage. External IDs become external references, and lifecycle ownership shifts to lifecycle_controller.

Changes

Billing API contract alignment

Layer / File(s) Summary
Charge models and lifecycle
api/spec/packages/aip/src/shared/enums.tsp, api/spec/packages/aip/src/customers/charges/charges.tsp, api/spec/packages/aip-client-javascript/src/models/..., api/v3/handlers/customers/charges/...
The lifecycle enum is renamed, charge models and create requests adopt Charge* names, lifecycle ownership moves to lifecycle_controller, and charge references are added.
Customer addresses and supplier snapshots
api/spec/packages/aip/src/customers/customer.tsp, api/spec/packages/aip-client-javascript/src/models/..., api/v3/handlers/{billingprofiles,customers}/...
Customer billing addresses move to shared Address, and supplier and invoice-customer snapshot shapes use the updated address and party types.
Invoice resource contracts
api/spec/packages/aip/src/invoices/{invoice.tsp,operations.tsp}, api/spec/packages/aip-client-javascript/src/models/..., api/spec/packages/aip-client-javascript/src/index.ts, api/spec/packages/aip-client-javascript/src/models/operations/customers.ts
Invoice base, standard, status, workflow, and external-reference contracts rename Billing* types to Invoice* names, and the generated client re-exports the renamed request and response types.
Invoice line and detail contracts
api/spec/packages/aip/src/invoices/invoice.tsp, api/spec/packages/aip-client-javascript/src/models/...
Invoice line, discount, rate-card, and detailed-line contracts rename line-specific types and switch to lifecycle_controller, ChargeReference, and external-reference fields.
Invoice runtime wiring
api/v3/handlers/billinginvoices/convert.go, api/v3/handlers/billingprofiles/convert.go, api/v3/handlers/customers/convert.gen.go, e2e/billinginvoices_v3_test.go
The invoice and customer converters map the renamed shapes, and the GET test decodes the new standard-invoice type.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • openmeterio/openmeter#4103: Both PRs touch the charge lifecycle conversion path and the managed_by/lifecycle controller renames in the customer charges API.

Suggested labels

area/api, kind/feature

Suggested reviewers

  • mark-vass-konghq
  • chrisgacsal
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 46.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is too generic and doesn't clearly describe the main change in the pull request. Use a concise, specific title that names the main change, such as the v3 invoice API rename/refactor.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/v3-invoice-api-get-review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR updates the v3 invoice and charge API contract. The main changes are:

  • Renamed invoice and charge models to the new Invoice* and Charge* shapes.
  • Replaced managed_by and external_ids with lifecycle_controller and external_references.
  • Added invoice payment references and charge references on invoice lines.
  • Reworked invoice customer and supplier snapshots around the shared address and party shapes.
  • Regenerated the Go API types, OpenAPI output, and TypeScript client models.

Confidence Score: 4/5

This is close, but the invoice workflow reference should be fixed before merging.

  • The updated invoice mapper can return a required billing-profile reference with an empty ID for invoices that lack the stored source profile.
  • The rest of the reviewed converter changes match the new generated schema shapes.

api/v3/handlers/billinginvoices/convert.go

Important Files Changed

Filename Overview
api/v3/handlers/billinginvoices/convert.go Maps domain invoices into the renamed v3 response shape, including workflow profile references, customer snapshots, line lifecycle controllers, and external references.
api/v3/handlers/customers/charges/convert.go Maps charge responses and create inputs to the renamed charge API models and the new lifecycle-controller field.
api/v3/handlers/billingprofiles/convert.go Updates supplier and party conversion so partial address snapshots are preserved in the new address wrapper shape.
api/spec/packages/aip/src/invoices/invoice.tsp Defines the new v3 invoice schema names, references, lifecycle-controller fields, and supplier/customer snapshot shapes.
api/v3/api.gen.go Regenerates the server API types for the updated v3 invoice and charge schema.

Fix All in Claude Code Fix All in Codex

Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
api/v3/handlers/billinginvoices/convert.go:183-186
**Empty Profile Reference**

When an older or migrated invoice has no `SourceBillingProfileID`, this now returns `source_billing_profile: {"id":""}` because the new response shape makes the profile reference object required. That gives callers a present billing-profile reference with an invalid ULID instead of failing conversion or omitting a nullable snapshot field, so clients that parse the reference as a real profile ID can reject otherwise readable invoices.

Reviews (6): Last reviewed commit: "fix: review comment" | Re-trigger Greptile

Comment thread api/v3/handlers/billinginvoices/convert.go Outdated
Comment thread api/spec/packages/aip/src/customers/charges/charges.tsp
Comment thread api/v3/handlers/billinginvoices/convert.go

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (1)
e2e/billinginvoices_v3_test.go (1)

221-237: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert one of the renamed invoice fields here too.

This subtest currently proves the union accessor rename, but none of the contract fields changed in this PR are actually exercised. Adding a couple of checks on workflow.source_billing_profile.id and the first line’s lifecycle_controller would make this test protect the converter changes, not just the renamed decoder.

Suggested assertions
 		stdInv, err := inv.AsBillingInvoiceStandard()
 		require.NoError(t, err, "expected invoice to decode as BillingInvoiceStandard")

 		assert.Equal(t, invoiceID, stdInv.Id)
 		assert.Equal(t, apiv3.BillingInvoiceStandardTypeStandard, stdInv.Type)
 		assert.Equal(t, apiv3.CurrencyCode("USD"), stdInv.Currency)
 		assert.NotEmpty(t, stdInv.Status)
 		assert.NotEmpty(t, stdInv.CreatedAt)
+		assert.NotEmpty(t, stdInv.Workflow.SourceBillingProfile.Id)
+		if assert.NotNil(t, stdInv.Lines) && assert.NotEmpty(t, *stdInv.Lines) {
+			assert.NotEmpty(t, (*stdInv.Lines)[0].LifecycleController)
+		}
 	})

As per path instructions, "Make sure the tests are comprehensive and cover the changes. Keep a strong focus on unit tests and in-code integration tests."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/billinginvoices_v3_test.go` around lines 221 - 237, The v3 invoice GET
test only verifies the union accessor rename, so it does not cover the renamed
contract fields changed in this PR. In the `Should return the invoice via v3
GET` subtest, add assertions against the decoded `BillingInvoiceStandard`
(`stdInv`) for `workflow.source_billing_profile.id` and the first line’s
`lifecycle_controller` so the converter changes are exercised as well. Use the
existing `AsBillingInvoiceStandard` decode path and assert the expected values
alongside the current `Id`, `Type`, `Currency`, `Status`, and `CreatedAt`
checks.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@api/spec/packages/aip-client-javascript/src/models/schemas.ts`:
- Around line 4468-4501: The runtime schema is missing the credit-note
discriminator variant, so fix the TypeSpec/generation source for invoice schemas
rather than editing generated output in aip-client-javascript. Update the
credit-note model behind invoiceCreditNote so its type is pinned to
z.literal('credit_note') instead of the broad invoiceType, and ensure the
top-level invoice discriminated union includes that credit-note variant
alongside invoiceStandard. After updating the source definition, regenerate the
client so invoice.parse(...) accepts real credit_note payloads and the
standalone schema has the correct discriminator.

In `@api/spec/packages/aip-client-javascript/src/models/types.ts`:
- Around line 2977-3009: The InvoiceCreditNote model has an incorrect
discriminator in the generated types, since the InvoiceCreditNote interface
currently uses the wrong type literal and should represent the credit note
variant instead. Update the underlying TypeSpec source for the InvoiceCreditNote
discriminator (not this generated types.ts file) so the model narrows correctly,
then regenerate the client artifacts to pick up the fix in the generated
InvoiceCreditNote definition.

In `@api/spec/packages/aip/src/invoices/invoice.tsp`:
- Around line 787-789: The summary for external_references is still using the
old “External IDs” label, so update the `@summary` on
InvoiceLineExternalReferences to match the renamed field and use terminology
consistent with the current API. Locate the external_references declaration in
the invoice model and change the summary text so generated docs and users see
the correct field name and meaning.
- Around line 295-304: The discriminator on InvoiceCreditNote is currently wired
to InvoiceType, but that enum only represents the standard invoice value, so the
model cannot correctly identify credit notes. Update the InvoiceCreditNote type
field to use the correct credit-note discriminator shape/value, and if needed
adjust InvoiceType or introduce a dedicated enum so the contract matches the
actual implementation and generated clients serialize the right type.

In `@api/v3/handlers/billingprofiles/convert.go`:
- Around line 162-168: The supplier snapshot conversion is being routed through
ToAPIBillingParty, but that helper only populates Addresses when
supplier.Address.Country is set, which drops line1/city/state/phone-only data.
Update ToAPIBillingParty (and any related address mapping it uses) so it emits
Addresses whenever any supplier address field is present, then keep
BillingSupplier conversion using that helper only if it preserves all address
fields.

---

Nitpick comments:
In `@e2e/billinginvoices_v3_test.go`:
- Around line 221-237: The v3 invoice GET test only verifies the union accessor
rename, so it does not cover the renamed contract fields changed in this PR. In
the `Should return the invoice via v3 GET` subtest, add assertions against the
decoded `BillingInvoiceStandard` (`stdInv`) for
`workflow.source_billing_profile.id` and the first line’s `lifecycle_controller`
so the converter changes are exercised as well. Use the existing
`AsBillingInvoiceStandard` decode path and assert the expected values alongside
the current `Id`, `Type`, `Currency`, `Status`, and `CreatedAt` checks.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f73281d2-7412-43e0-86cc-41c0f3ccb9ae

📥 Commits

Reviewing files that changed from the base of the PR and between 52c79c6 and 14c4c72.

⛔ Files ignored due to path filters (1)
  • api/v3/openapi.yaml is excluded by !**/openapi.yaml
📒 Files selected for processing (17)
  • .agents/skills/api/rules/aip-126-enums.md
  • api/spec/packages/aip-client-javascript/src/index.ts
  • api/spec/packages/aip-client-javascript/src/models/operations/customers.ts
  • api/spec/packages/aip-client-javascript/src/models/schemas.ts
  • api/spec/packages/aip-client-javascript/src/models/types.ts
  • api/spec/packages/aip/src/customers/charges/charges.tsp
  • api/spec/packages/aip/src/customers/customer.tsp
  • api/spec/packages/aip/src/invoices/invoice.tsp
  • api/spec/packages/aip/src/invoices/operations.tsp
  • api/spec/packages/aip/src/shared/enums.tsp
  • api/v3/api.gen.go
  • api/v3/handlers/billinginvoices/convert.go
  • api/v3/handlers/billingprofiles/convert.go
  • api/v3/handlers/customers/charges/convert.go
  • api/v3/handlers/customers/charges/create.go
  • api/v3/handlers/customers/convert.gen.go
  • e2e/billinginvoices_v3_test.go

Comment thread api/spec/packages/aip-client-javascript/src/models/schemas.ts Outdated
Comment thread api/spec/packages/aip-client-javascript/src/models/types.ts Outdated
Comment thread api/spec/packages/aip/src/invoices/invoice.tsp Outdated
Comment thread api/spec/packages/aip/src/invoices/invoice.tsp
Comment thread api/v3/handlers/billingprofiles/convert.go
Comment thread api/v3/handlers/billinginvoices/convert.go

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
api/spec/packages/aip/src/invoices/invoice.tsp (1)

33-34: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Keep the union docs aligned with the exposed variants.

credit_note is still listed in the public Invoice description, but the union member is commented out for now. That can make generated docs imply clients may receive a variant the schema doesn’t allow yet.

Suggested tweak
- * - `standard`: a standard invoice for charges owed.
- * - `credit_note`: a credit note reducing a previous invoice amount.
+ * - `standard`: a standard invoice for charges owed.

As per path instructions, "The declared API should be accurate, in parity with the actual implementation, and easy to understand for the user."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@api/spec/packages/aip/src/invoices/invoice.tsp` around lines 33 - 34, The
public Invoice union docs still mention a variant that is not currently exposed,
so the description is out of sync with the actual schema. Update the
documentation near the Invoice type in invoice.tsp to match only the active
union members, and keep any mention of credit_note aligned with whether the
variant is actually declared in the Invoice union or removed from the docs until
it is re-enabled.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@api/spec/packages/aip/src/invoices/invoice.tsp`:
- Around line 33-34: The public Invoice union docs still mention a variant that
is not currently exposed, so the description is out of sync with the actual
schema. Update the documentation near the Invoice type in invoice.tsp to match
only the active union members, and keep any mention of credit_note aligned with
whether the variant is actually declared in the Invoice union or removed from
the docs until it is re-enabled.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ebe6b2e3-b594-4fb3-a94d-95342abaf9c1

📥 Commits

Reviewing files that changed from the base of the PR and between 14c4c72 and 55437c0.

⛔ Files ignored due to path filters (1)
  • api/v3/openapi.yaml is excluded by !**/openapi.yaml
📒 Files selected for processing (6)
  • api/spec/packages/aip-client-javascript/src/index.ts
  • api/spec/packages/aip-client-javascript/src/models/schemas.ts
  • api/spec/packages/aip-client-javascript/src/models/types.ts
  • api/spec/packages/aip/src/invoices/invoice.tsp
  • api/v3/api.gen.go
  • api/v3/handlers/billinginvoices/convert.go
💤 Files with no reviewable changes (1)
  • api/spec/packages/aip-client-javascript/src/index.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • api/v3/handlers/billinginvoices/convert.go
  • api/spec/packages/aip-client-javascript/src/models/schemas.ts
  • api/spec/packages/aip-client-javascript/src/models/types.ts

Comment thread api/v3/handlers/billinginvoices/convert.go
@tothandras
tothandras force-pushed the feat/v3-invoice-api-get-review branch from 658c940 to 7c9ff4e Compare June 25, 2026 19:17
Comment thread api/v3/handlers/billinginvoices/convert.go
@tothandras
tothandras force-pushed the feat/v3-invoice-api-get-review branch from 7c9ff4e to 6c98216 Compare June 25, 2026 19:47
Comment thread api/v3/handlers/billinginvoices/convert.go Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@api/spec/packages/aip-client-javascript/src/models/types.ts`:
- Around line 1446-1447: The generated JSDoc for the renamed external_references
fields still says “External identifiers,” so update the corresponding TypeSpec
comments to use “external references” and regenerate the aip-client-javascript
types instead of editing types.ts directly. Make this change for the affected
model definitions that feed the external_references properties, then re-run
generation so all listed occurrences pick up the new wording consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: cbcb0527-3b49-4b82-8220-18bc0e94d8bf

📥 Commits

Reviewing files that changed from the base of the PR and between 7c9ff4e and 6c98216.

⛔ Files ignored due to path filters (1)
  • api/v3/openapi.yaml is excluded by !**/openapi.yaml
📒 Files selected for processing (17)
  • .agents/skills/api/rules/aip-126-enums.md
  • api/spec/packages/aip-client-javascript/src/index.ts
  • api/spec/packages/aip-client-javascript/src/models/operations/customers.ts
  • api/spec/packages/aip-client-javascript/src/models/schemas.ts
  • api/spec/packages/aip-client-javascript/src/models/types.ts
  • api/spec/packages/aip/src/customers/charges/charges.tsp
  • api/spec/packages/aip/src/customers/customer.tsp
  • api/spec/packages/aip/src/invoices/invoice.tsp
  • api/spec/packages/aip/src/invoices/operations.tsp
  • api/spec/packages/aip/src/shared/enums.tsp
  • api/v3/api.gen.go
  • api/v3/handlers/billinginvoices/convert.go
  • api/v3/handlers/billingprofiles/convert.go
  • api/v3/handlers/customers/charges/convert.go
  • api/v3/handlers/customers/charges/create.go
  • api/v3/handlers/customers/convert.gen.go
  • e2e/billinginvoices_v3_test.go
✅ Files skipped from review due to trivial changes (2)
  • .agents/skills/api/rules/aip-126-enums.md
  • api/spec/packages/aip-client-javascript/src/models/operations/customers.ts
🚧 Files skipped from review as they are similar to previous changes (13)
  • api/spec/packages/aip/src/customers/customer.tsp
  • api/v3/handlers/customers/charges/create.go
  • e2e/billinginvoices_v3_test.go
  • api/spec/packages/aip/src/invoices/operations.tsp
  • api/v3/handlers/billingprofiles/convert.go
  • api/v3/handlers/customers/convert.gen.go
  • api/spec/packages/aip/src/shared/enums.tsp
  • api/v3/handlers/billinginvoices/convert.go
  • api/v3/handlers/customers/charges/convert.go
  • api/spec/packages/aip-client-javascript/src/index.ts
  • api/spec/packages/aip/src/customers/charges/charges.tsp
  • api/spec/packages/aip-client-javascript/src/models/schemas.ts
  • api/spec/packages/aip/src/invoices/invoice.tsp

Comment thread api/spec/packages/aip-client-javascript/src/models/types.ts
Comment thread api/v3/handlers/billinginvoices/convert.go

@turip turip left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checked the LifecycleController handler conversions. The mappings are consistent with the public contract: manual stays manual, and both system/subscription-owned domain resources surface as system. Looks good.

@tothandras
tothandras merged commit 3188916 into feat/v3-invoice-api-get Jun 25, 2026
41 of 45 checks passed
@tothandras
tothandras deleted the feat/v3-invoice-api-get-review branch June 25, 2026 20:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-note/feature Release note: Exciting New Features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants